package com.ly.mp.busicen.rule.flow;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;

import org.springframework.asm.Type;
import org.springframework.cglib.core.NamingPolicy;
import org.springframework.cglib.core.Predicate;
import org.springframework.cglib.core.Signature;
import org.springframework.cglib.core.SpringNamingPolicy;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.InterfaceMaker;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import com.ly.mp.busicen.common.constant.UserBusiEntity;
import com.ly.mp.busicen.rule.flow.action.ActionExecuteBase.Extention;

public class DynamicTypeLib {
	
	static {
		
		InterfaceMaker im = new InterfaceMaker();
		im.add(new Signature("get__user", Type.getType(UserBusiEntity.class), new Type[] {}), null);
		im.add(new Signature("get__extention", Type.getType(Extention.class), new Type[] {}), null);
		USER_WRAP_INTERFACE = im.create();
	}
	/**
	 * 用户包装动态接口
	 */
	public final static Class<?> USER_WRAP_INTERFACE;
	
	public final static Map<String,Class<?>> XRULE_FLOW_SERVICES = new HashMap<>();
	
	public final static String XRULE_COMMON_SERVICE_STRING="com.xrule.dynamic.%s.service";
	
	interface XruleService{
		Object flow(String flow,Map<String, Object> data);
	}
	
	public static void initXRULE_FLOW_SERVICES(String... centers) {
		if (centers==null) {
			return;
		}		
		
		Stream.of(centers).forEach(m->{
			if (!XRULE_FLOW_SERVICES.containsKey(m)) {
				NamingPolicy namingPolicy = new NamingPolicy() {			
					@Override
					public String getClassName(String arg0, String arg1, Object arg2, Predicate arg3) {
						return String.format(XRULE_COMMON_SERVICE_STRING, m);
					}
				};
				InterfaceMaker ifm = new InterfaceMaker();				
				ifm.setNamingPolicy(namingPolicy);
				ifm.add(new Signature("flow", Type.getType(Object.class), new Type[] {Type.getType(String.class),Type.getType(Map.class)}), null);
				Class<?> interfaceTemp = ifm.create();
				XRULE_FLOW_SERVICES.put(m, interfaceTemp);
			}
		});
	}
	
	@SuppressWarnings("unchecked")
	public static <T> T enhanceEntry(Class<T> interfacing,Object entry) {
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(entry.getClass());
		enhancer.setInterfaces(new Class[] { interfacing });
		enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
		enhancer.setCallback(new MethodInterceptor() {
			@Override
			public Object intercept(Object obj, Method method, Object[] param, MethodProxy px) throws Throwable {
				Object result = method.invoke(entry, param);
				return result;
			}
		});
		return (T) enhancer.create();
	}
	
	
	class XruleServiceSimple implements XruleService{

		@Override
		public Object flow(String flow, Map<String, Object> data) {
			return "flow";
		}
		
	}
	
	public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException  {
		initXRULE_FLOW_SERVICES("prc");
		XruleService entry = new XruleService() {			
			@Override
			public Object flow(String flow, Map<String, Object> data) {				
				return flow;
			}
		};
		Object xxObject=enhanceEntry(XRULE_FLOW_SERVICES.get("prc"), entry);
		
		XruleService entry2 = new XruleService() {			
			@Override
			public Object flow(String flow, Map<String, Object> data) {				
				return flow;
			}
		};
		Object xxObject2=enhanceEntry(XRULE_FLOW_SERVICES.get("prc"), entry2);
		
		System.out.println(xxObject.getClass().equals(xxObject2.getClass()));
		
		Object result = Stream.of(XRULE_FLOW_SERVICES.get("prc").getMethods()).filter(m->"flow".equals(m.getName()))
			.findAny().get()
			.invoke(xxObject, "prc_001",null);
		System.out.println(result);
		
	}
	
	


}
